package com.easybbs.controller;

import com.easybbs.annotation.Globallnterceptor;
import com.easybbs.entity.config.WebConfig;
import com.easybbs.entity.constants.Constants;
import com.easybbs.entity.enums.ResponseCodeEnum;
import com.easybbs.entity.enums.UserOperFrequencyTypeEnum;
import com.easybbs.entity.vo.ResponseVO;
import com.easybbs.exception.BusinessException;
import com.easybbs.utils.StringTools;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/file")
public class FileController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private WebConfig webConfig;

    /**
     * 图片上传
     *
     * @param file
     * @return
     */
    @RequestMapping("/uploadImage")
    @Globallnterceptor(checkLogin = true, frequencyType = UserOperFrequencyTypeEnum.IMAGE_UPLAOD)
    public ResponseVO uploadImage(MultipartFile file) {
        if (file == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        String fileName = file.getOriginalFilename(); // 获取文件名
        String fileExtName = StringTools.getFileSuffix(fileName); // 获取文件后缀
        if (!ArrayUtils.contains(Constants.IMAGE_SUFFIX, fileExtName)) {
            throw new BusinessException("请选择图片文件上传");
        }
        String path = copyFile(file);
        //将文件复制一份
        Map<String, String> fileMap = new HashMap<>();
        fileMap.put("fileName", path);
        //返回结果
        return getSuccessResponseVO(fileMap);
    }

    //文件上传方法
    private String copyFile(MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename();
            String fileExtName = StringTools.getFileSuffix(fileName);
            //重命名文件 防止重命名
            String fileRealName = StringTools.getRandomString(Constants.LENGTH_30) + "." + fileExtName;
            //将文件存到临时目录中 防止一直提交不上传
            String folderPath = webConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLEDR_TEMP;
            File folder = new File(folderPath);
            if (!folder.exists()) {
                folder.mkdirs();
            }

            //上传到服务器的文件路径
            File uploadFile = new File(folderPath + "/" + fileRealName);
            file.transferTo(uploadFile);
            return Constants.FILE_FOLDER_TEMP_2 + "/" + fileRealName;
        } catch (Exception e) {
            logger.error("上传文件失败", e);
            throw new BusinessException("上传文件失败");
        }
    }

    /**
     * 获取图片
     *
     * @param response
     * @param imageFolder
     * @param imageName
     */
    @RequestMapping("/getImage/{imageFolder}/{imageName}")
    public void getImage(HttpServletResponse response,
                         @PathVariable("imageFolder") String imageFolder,
                         @PathVariable("imageName") String imageName) {
        readImage(response, imageFolder, imageName);
    }

    /**
     * 获取用户头像
     * @param response
     * @param userId
     */
    @RequestMapping("/getAvatar/{userId}")
    @Globallnterceptor(checkLogin = false, checkParams = true)
    public void getAvatar(HttpServletResponse response,
                          @PathVariable("userId") String userId
    ) {
        //头像路径名
        String avatarFolderName = Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_AVATAR_NAME;
        //完整头像图片路径
        String avatarPath = webConfig.getProjectFolder() + avatarFolderName + userId + Constants.AVATAR_SUFFIX;

        //判断路径是否存在
        File avatarFloder = new File(avatarFolderName);
        if (!avatarFloder.exists()) {
            avatarFloder.mkdirs();
        }

        //转换头像为文件
        File file = new File(avatarPath);

        //存在的文件名 以userid加后缀.jpg命名
        String imageName = userId + Constants.AVATAR_SUFFIX;

        //请求的时候当前文件名没有 读取默认头像
        if (!file.exists()) {
            imageName = Constants.AVATAR_DEFAULT;
        }

        readImage(response, Constants.FILE_FOLDER_AVATAR_NAME, imageName);
    }

    /**
     * 读取显示图片的文件
     *
     * @param response
     * @param imageFolder
     * @param imageName
     */
    private void readImage(HttpServletResponse response, String imageFolder, String imageName) {
        // 声明ServletOutputStream对象
        ServletOutputStream sos = null;
        // 声明FileInputStream对象
        FileInputStream in = null;
        // 声明ByteArrayOutputStream对象
        ByteArrayOutputStream baos = null;
        // 尝试读取文件
        try {
            // 如果imageFolder为空或者imageName为空，则返回
            if (StringTools.isEmpty(imageFolder) || StringUtils.isBlank(imageName)) {
                return;
            }
            // 获取文件后缀
            String imageSuffix = StringTools.getFileSuffix(imageName);
            // 拼接文件路径
            String filePath = webConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_IMAGE + imageFolder + "/" + imageName;
            // 如果imageFolder为临时文件夹，则拼接临时文件夹路径
            if (Constants.FILE_FOLDER_TEMP_2.equals(imageFolder)) {
                filePath = webConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + imageFolder + "/" + imageName;
                // 如果imageFolder包含avatar名称，则拼接avatar文件夹路径
            } else if (imageFolder.contains(Constants.FILE_FOLDER_AVATAR_NAME)) {
                filePath = webConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + imageFolder + imageName;
            }
            // 创建文件对象
            File file = new File(filePath);
            // 如果文件不存在，则返回
            if (!file.exists()) {
                return;
            }
            // 获取文件后缀
            imageSuffix = imageSuffix.replace(".", "");
            // 如果imageFolder不是avatar文件夹，则设置响应头
            if (!Constants.FILE_FOLDER_AVATAR_NAME.equals(imageFolder)) {
                response.setHeader("Cache-Control", "max-age=2592000");
            }
            // 设置响应类型
            response.setContentType("image/" + imageSuffix);
            // 创建FileInputStream对象
            in = new FileInputStream(file);
            // 创建ServletOutputStream对象
            sos = response.getOutputStream();
            // 创建ByteArrayOutputStream对象
            baos = new ByteArrayOutputStream();
            // 读取文件内容
            int ch = 0;
            while (-1 != (ch = in.read())) {
                baos.write(ch);
            }
            // 将文件内容写入ServletOutputStream
            sos.write(baos.toByteArray());
        } catch (Exception e) {
            logger.error("读取图片异常", e);
        } finally {
            // 关闭ByteArrayOutputStream对象
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 关闭ServletOutputStream对象
            if (sos != null) {
                try {
                    sos.close();
                } catch (IOException e) {
                    logger.error("IO异常", e);
                }
            }
            // 关闭FileInputStream对象
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("IO异常", e);
                }
            }
        }
    }
}
